package com.qf.strategy.service.Impl;

import com.qf.strategy.feign.CacheService;
import com.qf.strategy.service.FilterChain;
import com.qianfeng.smsplatform.common.constants.CacheConstants;
import com.qianfeng.smsplatform.common.model.Standard_Submit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Set;
import java.util.UUID;
import java.util.zip.DataFormatException;

/**
 * @author 徐老板
 * @date 2020/3/2   14:28
 */
//写完之后记得把这个过滤器加到redis中
@Service
public class SmsLimitFilter implements FilterChain
{
    private static final  Logger LOGGER = LoggerFactory.getLogger(SmsLimitFilter.class);
    @Resource
    CacheService cacheService;

    @Override
    public boolean dealSms(Standard_Submit submit) throws DataFormatException, IOException {
        long nowMinutes = System.currentTimeMillis();
        //限流
        //我们要先解释名词,定义什么是限流
        //我们的限流的是同一个客户给同一个手机号发送的短信的数量有限制
        //比如我们的限制是 每分钟 不能超过 3 条,每小时不能超过 5 条,每天不能超过 10 条
        //我们如何判断,只要出现如何怎么做等等就需要有地方保存数据来进行判断的
        //数据保存在什么地方,然后怎么获取怎么判断呢,比如使用客户 id+手机号的方式作为 key,次数作为 value,那么如何判断,因为会出现用户在一分钟内连续发 3 次了,想要发第四次,如何判断出来是在一分钟内,如何判断到底属于哪个时间范围
        //学习要灵活运用啊,redis 中的 zset 你们可能学习的时候多少分数之间有多少个学生,能不能知道多少时间范围内有多少数据
        //用户每次发送短信 key 是用户 id 和手机号, 值随便写,分数写当前时间的毫秒值, 后面我们可以通过两个毫秒值来获取中间的数据的数量,现在只要确定两个毫秒值, 一个是就是我现在就要发送短信的时间,一个是减去对应时间差的时间
        //获取我们想要发送短息你的时间
        //==============上面是老师定义的规则 这里有关电话号码的东西已经存入redis 只需要取出来比较即可 格式是zset的==========================
        long currentTimeMillis = System.currentTimeMillis();
        long oneMinute = currentTimeMillis - 60000;
        //你看这里用的就是long类型的参数了 所以我感觉之前那个range方法是可以的 有空试一下一会
        Set<Object> objects = cacheService.zRangeByScore(CacheConstants.CACHE_PREFIX_SMS_LIMIT + submit.getClientID() + submit.getDestMobile(), oneMinute, currentTimeMillis);
        if (objects!=null&&objects.size()>=3){
            LOGGER.error("超过一分钟限制了");
        }else {
            long oneDay = currentTimeMillis - (60000 * 60 * 24);
            //这个地方有一个理解的问题就是range方法也是从数据库中取值的方法 这个和之前的认知有些出入 注意
            Set<Object> rangeByScore = cacheService.zRangeByScore(CacheConstants.CACHE_PREFIX_SMS_LIMIT + submit.getClientID() + submit.getDestMobile(), oneDay, currentTimeMillis);
            if (rangeByScore!=null&&rangeByScore.size()>=5){
                LOGGER.error("超过一天限制了");
            }else {
                LOGGER.error("没有超出限制");
                //这个时候就可以把这个放进缓存中了
                cacheService.addZet(CacheConstants.CACHE_PREFIX_SMS_LIMIT + submit.getClientID() + submit.getDestMobile(), UUID.randomUUID().toString(),currentTimeMillis );
                return true;
            }
        }

        return false;
    }
}
